package com.kai.steering.data.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.kai.steering.common.vo.Result;
import com.kai.steering.common.web.vo.ReturnCodeExt;
import com.kai.steering.data.service.entity.AnswerResult;
import com.kai.steering.data.service.entity.domainObject.*;
import com.kai.steering.data.service.entity.dto.QuestionQueryDTO;
import com.kai.steering.data.service.entity.po.Knowledge;
import com.kai.steering.data.service.entity.po.Question;
import com.kai.steering.data.service.entity.po.TestQuestion;
import com.kai.steering.data.service.entity.vo.QuestionVO;
import com.kai.steering.data.service.mapper.QuestionMapper;
import com.kai.steering.data.service.service.*;
import com.kai.steering.common.web.service.impl.BaseServiceImpl;
import com.kai.steering.common.vo.Page;

import com.kai.steering.data.service.util.ConfigurationReading.TestExcelAllocation;
import com.kai.steering.data.service.util.EqualsUtil;
import com.kai.steering.data.service.util.ListUtil;
import com.kai.steering.data.service.util.OfficeUtil;
import com.kai.steering.exception.ExcelException;
import com.kai.steering.exception.UimpException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.bean.BeanUtil;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.HttpHeaders;

/**
 * <pre>
 * 题目 服务实现类
 * </pre>
 *
 * @author kai
 * @since 2022-02-23
 */
@Slf4j
@Service
public class QuestionServiceImpl extends BaseServiceImpl<QuestionMapper, Question> implements QuestionService {

    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private ClassificationService classificationService;
    @Autowired
    private KnowledgeService knowledgeService;
    @Autowired
    private AnswerService answerService;
    @Autowired
    private QuestionDetailsService questionDetailsService;
    @Autowired
    UserQuestionService userQuestionService;
    @Autowired
    NoteService noteService;
    @Autowired
    TestQuestionService testQuestionService;
    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    AnswerJournalService answerJournalService;

    @Autowired
    private TestExcelAllocation testExcelAllocation;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public QuestionDO saveQuestion(QuestionDO questionDO) {
        /**
         * 参数校验
         */
        //校验题目分类
        if (questionDO.getClassificationDO() == null || (StringUtils.isEmpty(questionDO.getClassificationDO().getClassificationId())
                && StringUtils.isEmpty(questionDO.getClassificationDO().getClassificationName()))) {
            throw ReturnCodeExt.PARAMETER_CHECK.getException("类型不存在");
        }
        if (!StringUtils.isEmpty(questionDO.getClassificationDO().getClassificationId())) {
            questionDO.setClassificationDO(classificationService.getClassificationById(questionDO.getClassificationDO().getClassificationId()));
        } else {
            ClassificationDO classificationByName = classificationService.getClassificationByName(questionDO.getClassificationDO().getClassificationName());
            questionDO.setClassificationDO(classificationByName);

        }
        if (StringUtils.isEmpty(questionDO.getClassificationDO().getClassificationId())) {
            throw ReturnCodeExt.PARAMETER_CHECK.getException(questionDO.getClassificationDO().getClassificationId() + "类型不存在");
        }
        //校验知识点
        if (questionDO.getKnowledgeDOs() != null) {

            boolean allExists = knowledgeService.isAllExists(questionDO.getKnowledgeDOs());
            if (!allExists) {
                throw ReturnCodeExt.PARAMETER_CHECK.getException("知识不存在");
            }
        }


        //question
        Question question = new Question(questionDO);
        question.setCreationDatetime(new Date());
        question.setDeleteDatetime(null);
        super.save(question);
        QuestionDO newQuestionDO = new QuestionDO(question);


        //QuestionDetails
        if (questionDO.getQuestionDetailsDO() != null) {
            QuestionDetailsDO questionDetailsDO = questionDO.getQuestionDetailsDO();
            questionDetailsDO.setQuestionId(question.getQuestionId());
            QuestionDetailsDO newQuestionDetailsDO = questionDetailsService.saveQuestionDetails(questionDetailsDO);
            newQuestionDO.setQuestionDetailsDO(newQuestionDetailsDO);
        }

        //AnswerDO
        //判断有无标准答案
        if (questionDO.getStandardAnswer() != null) {
            if (questionDO.getAnswerDO() == null) {
                questionDO.setAnswerDO(new ArrayList<AnswerDO>());
            }
            questionDO.getAnswerDO().add(questionDO.getStandardAnswer());
        }

        if (questionDO.getAnswerDO() != null && questionDO.getAnswerDO().size() > 0) {
            List<AnswerDO> answerDOs = questionDO.getAnswerDO();
            for (AnswerDO answerDO : answerDOs) {
                answerDO.setQuestionId(question.getQuestionId());
            }
            List<AnswerDO> answerDOS = answerService.saveAnswerBatch(answerDOs);
            newQuestionDO.setAnswerDO(answerDOS);
            //有标准答案
            if (questionDO.getStandardAnswer() != null) {
                //添加题目的标准答案
                AnswerDO answerDO = answerDOS.get(answerDOS.size() - 1);

                question.setStandardAnswer(answerDO.getAnswerId());
                updateById(question);
                newQuestionDO.setStandardAnswer(answerDO);

            }
        }


        return newQuestionDO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateQuestion(Serializable id, QuestionDO questionDO) {
        /**
         * 验证参数
         */

        HashMap<String, Boolean> parameterMap = new HashMap<>();
        parameterMap.put("questionDetailsExist",true);
        //id
        QuestionDO oldQuestionDO = getQuestionById(id, parameterMap);
        if (oldQuestionDO == null || oldQuestionDO.getQuestionId() == null) {
            throw ReturnCodeExt.PARAMETER_CHECK.getException("题目:" + id + "不存在");
        }
        questionDO.setQuestionId(id.toString());

        /**
         * 更新
         */
        //更新详情:没有详情的添加详情，有详情的，判断是否需要更新
        if (questionDO.getQuestionDetailsDO() != null && questionDO.getQuestionDetailsDO().getContent() != null) {
            if (oldQuestionDO.getQuestionDetailsDO() == null && oldQuestionDO.getQuestionDetailsDO().getContent() == null) {
                QuestionDetailsDO questionDetailsDO = questionDO.getQuestionDetailsDO();
                questionDetailsDO.setQuestionId(questionDO.getQuestionId());
                QuestionDetailsDO newQuestionDetailsDO = questionDetailsService.saveQuestionDetails(questionDetailsDO);
                if (newQuestionDetailsDO == null) {
                    throw ReturnCodeExt.BUSINESS_EXCEPTION.getException("题目详情:" + questionDO.getQuestionDetailsDO().getContent() + "保存失败");

                }
            } else {
                boolean b = questionDetailsService.updateQuestionDetails(oldQuestionDO.getQuestionDetailsDO().getQuestionDetailsId(),
                        questionDO.getQuestionDetailsDO());
                if (!b) {
                    throw ReturnCodeExt.BUSINESS_EXCEPTION.getException("题目详情:" + questionDO.getQuestionDetailsDO().getQuestionDetailsId() + "更新失败");
                }
            }
        }

        Question question = new Question(questionDO);
        return super.updateById(question);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteQuestion(Serializable id) {
        QuestionDO questionById = getQuestionById(id, null);
        if (questionById == null) {
            throw ReturnCodeExt.DAO_EXCEPTION.getException("id不存在");
        }

        boolean b = super.removeById(id);
        return b;
    }


    @Override
    public QuestionDO getQuestionById(Serializable questionId,HashMap<String,Boolean>parameterMap) {
        /**
         * 参数检查
         */
        Question question = super.getById(questionId);
        if (question == null || question.getQuestionId() == null) {
            return null;
        }
        QuestionDO questionDO = new QuestionDO(question);
        if (parameterMap!=null) {

        if (EqualsUtil.objectBooleanEquals(parameterMap.get("questionDetailsExist")) && questionId != null) {


            QuestionDetailsDO questionDetails = questionDetailsService.getQuestionDetailsByQId(questionId);

            questionDO.setQuestionDetailsDO(questionDetails);
        }


        if (EqualsUtil.objectBooleanEquals(parameterMap.get("standardAnswerExist"))) {
            AnswerDO answerById = answerService.getAnswerById(question.getStandardAnswer());
            questionDO.setStandardAnswer(answerById);

        }
        if (EqualsUtil.objectBooleanEquals(parameterMap.get("answerAllExist")) && !EqualsUtil.objectBooleanEquals(parameterMap.get("standardAnswer") )) {
            List<AnswerDO> answerById = answerService.getAnswerByQId(questionId);
            questionDO.setAnswerDO(answerById);

        }
        if (EqualsUtil.objectBooleanEquals(parameterMap.get("classificationExist")) && question.getClassificationId() != null) {
            String classificationId = question.getClassificationId();
            ClassificationDO classificationById = classificationService.getClassificationById(classificationId);
            questionDO.setClassificationDO(classificationById);
        } else {
            questionDO.getClassificationDO().setClassificationId(question.getClassificationId());
        }
        if (EqualsUtil.objectBooleanEquals(parameterMap.get("knowledgeExist")) && question.getKnowledgeId() != null) {
            List<String> knowledgeIds = Arrays.asList(StringUtils.splitByWholeSeparator(question.getKnowledgeId(), ","));
            List<KnowledgeDO> knowledgeByIds = knowledgeService.getKnowledgeByIds(knowledgeIds);
            questionDO.setKnowledgeDOs(knowledgeByIds);
        } else {
            List<String> knowledgeIds = Arrays.asList(StringUtils.splitByWholeSeparator(question.getKnowledgeId(), ","));
            List<KnowledgeDO> collect = knowledgeIds.stream().map(s -> {
                return new KnowledgeDO(s);
            }).collect(Collectors.toList());
            questionDO.setKnowledgeDOs(collect);
        }
        if (EqualsUtil.objectBooleanEquals(parameterMap.get("userExist"))) {
            //获取当前用户
            UserDO userDO = new UserDO();
            userDO.setUserId("000000");

            //获取用户和题目关系
            UserQuestionDO userQuestionDO = userQuestionService.getUserQuestion(userDO.getUserId(), questionId.toString(),EqualsUtil.objectBooleanEquals(parameterMap.get("noteExist")) );

            questionDO.setUserQuestionDO(userQuestionDO);

        }

        }

        return questionDO;
    }

    @Override
    public QuestionDO getQuestionById_All(Serializable questionId) {
        /**
         * 参数检查
         */
        Question question = super.getById(questionId);
        if (question == null && question.getQuestionId() == null) {
            return null;
        }
        /**
         * 获取对象
         */
        QuestionDO questionDO = questionMapper.getQuestionById_All(questionId);

        return questionDO;
    }

    @Override
    public QuestionDO getQuestionById_VO(Serializable questionId) {
        /**
         * 参数检查
         */
        Question question = super.getById(questionId);
        if (question == null && question.getQuestionId() == null) {
            return null;
        }
        /**
         * 获取对象
         */
        QuestionDO questionDO = questionMapper.getQuestionById_VO(questionId);

        return questionDO;
    }

    @Override
    public List<QuestionVO> getAllQuestion() {
        List<Question> questionlist = questionMapper.selectList(new QueryWrapper<Question>());
        List<QuestionVO> result = questionlist.stream()
                .map(question -> {
                    QuestionVO questionVo = new QuestionVO();
                    BeanUtil.copyProperties(question, questionVo);
                    return questionVo;
                })
                .collect(Collectors.toList());
        return result;
    }

    @Override
    public Page<QuestionVO> getQuestionPageList(QuestionQueryDTO questionQueryDTO) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page page = setPageParam(
                questionQueryDTO, OrderItem.desc("create_time")
        );

        QueryWrapper<Question> queryWrapper = new QueryWrapper<>();

        //组合条件
        IPage<Question> entityPage = questionMapper.selectPage(page, queryWrapper);
        List<QuestionVO> result = entityPage.getRecords().stream()
                .map(question -> {
                    QuestionVO questionVo = new QuestionVO();
                    BeanUtil.copyProperties(question, questionVo);
                    return questionVo;
                })
                .collect(Collectors.toList());

        return Page.<QuestionVO>builder()
                .currPage(questionQueryDTO.getPageNo())
                .pageSize(questionQueryDTO.getPageSize())
                .totalCount((int) entityPage.getTotal())
                .list(result)
                .build();
    }


    @Override
    public boolean isExists(String key, String val, Serializable id) {
        QueryWrapper<Question> qw = new QueryWrapper<>();
        qw.eq(key, val);
        if (id != null) {
            qw.ne("id", id);
        }
        int num = this.count(qw);
        return num > 0;
    }

    @Override
    public List<QuestionDO> getQuestionByIds(List<String> questions, HashMap<String,Boolean> parameterMap) {
        if (CollUtil.isEmpty(questions)) {
            return null;
        }
        QueryWrapper<Question> qw = new QueryWrapper<>();
        qw.in("question_id", questions);
        List<Question> list = super.list(qw);
        List<QuestionDO> questionDOS = list.stream().map(question -> new QuestionDO(question)).collect(Collectors.toList());

        List<String> answerIds = list.stream().map(question -> question.getStandardAnswer()).collect(Collectors.toList());

        if (parameterMap!=null) {
            if (EqualsUtil.objectBooleanEquals(parameterMap.get("questionUserExist")) ) {
                Map<String, UserQuestionDO> userQuestionMap = userQuestionService.getUserQuestionMap("000000", questions, false);
                for (QuestionDO questionDO : questionDOS) {
                    questionDO.setUserQuestionDO(userQuestionMap.get(questionDO.getQuestionId()));
                }
            }
            if (EqualsUtil.objectBooleanEquals(parameterMap.get("questionDetailsExist"))){
                Map<String, QuestionDetailsDO> questionDetailsMap = questionDetailsService.getQuestionDetailsMap(questions);
                for (QuestionDO questionDO : questionDOS) {
                    questionDO.setQuestionDetailsDO(questionDetailsMap.get(questionDO.getQuestionId()));
                }
            }
            if (EqualsUtil.objectBooleanEquals(parameterMap.get("questionsAnswerExist"))){
                Map<String, AnswerDO> questionDetailsMap = answerService.getAnswerByQId(answerIds);
                for (QuestionDO questionDO : questionDOS) {
                    questionDO.setStandardAnswer(questionDetailsMap.get(questionDO.getQuestionId()));
                }
            }
            if (EqualsUtil.objectBooleanEquals(parameterMap.get("knowledgeExist")) ) {
                for (int i = 0; i < questionDOS.size(); i++) {
                    List<String> knowledgeIds = Arrays.asList(StringUtils.splitByWholeSeparator(list.get(i).getKnowledgeId(), ","));
                    List<KnowledgeDO> knowledgeByIds = knowledgeService.getKnowledgeByIds(knowledgeIds);
                    questionDOS.get(i).setKnowledgeDOs(knowledgeByIds);
                }
            }
        }




        return questionDOS;
    }

    @Override
    public boolean exportQuestion(List<String> questionIds) {

        return false;
    }


    @Override
    public List<ExcelException> importQuestion(MultipartFile file, int page, int start) {

        List<List> surface = null;
        try {
            surface = OfficeUtil.excelReaderPage(file.getInputStream(), page);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<List> questionData = surface.subList(start + 1, surface.size());

        ArrayList<QuestionDO> questionDOs = tableConversionQuestionDO(questionData);
        List<ExcelException> incorrectDataS = saveQuestionAll(questionDOs);
        return incorrectDataS;
    }

    @Override
    public ArrayList<QuestionDO> tableConversionQuestionDO(List<List> questionData) {
        ArrayList<QuestionDO> questionDOs = new ArrayList<>();

        for (int i = 0; i < questionData.size(); i++) {
            Object resultString = null;
            List line = questionData.get(i);
            ClassificationDO classificationByName = null;
            QuestionDO questionDO = new QuestionDO();
            resultString = ListUtil.lineAcquisition(line, testExcelAllocation.getQuestionColumn());

            questionDO.setQuestion(resultString == null ? null : resultString.toString());//题目

            QuestionDetailsDO questionDetailsDO = new QuestionDetailsDO();
            resultString = ListUtil.lineAcquisition(line, testExcelAllocation.getQuestionDetailsColumn());

            questionDetailsDO.setContent(resultString == null ? null : resultString.toString());
            questionDO.setQuestionDetailsDO(questionDetailsDO);//题目详情

            ClassificationDO classificationDO = new ClassificationDO();
            resultString = ListUtil.lineAcquisition(line, testExcelAllocation.getClassificationColumn());
            classificationDO.setClassificationName(resultString == null ? null : resultString.toString());
            questionDO.setClassificationDO(classificationDO);//分类


            resultString = ListUtil.lineAcquisition(line, testExcelAllocation.getKnowledgeColumn());
            List<KnowledgeDO> knowledgeDOS = KnowledgeDO.converKnowledgeDO(resultString == null ? null : resultString.toString());
            questionDO.setKnowledgeDOs(knowledgeDOS);//知识点

            AnswerDO answerDO = new AnswerDO();
            resultString = ListUtil.lineAcquisition(line, testExcelAllocation.getAnswerColumn());
            answerDO.setAnswer(resultString == null ? null : resultString.toString());//题目

            resultString = ListUtil.lineAcquisition(line, testExcelAllocation.getAnswerDetailsColumn());
            answerDO.setContent(resultString == null ? null : resultString.toString());//题目详情
            questionDO.setStandardAnswer(answerDO);//题目
            questionDOs.add(questionDO);

        }
        return questionDOs;
    }

    @Override
    public List<ExcelException> saveQuestionAll(List<QuestionDO> questionDOs) {
        ArrayList<ExcelException> incorrectDataS = new ArrayList<>();
        boolean abnormalOccurrence = false;
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);


        for (int i = 0; i < questionDOs.size(); i++) {

            try {
                QuestionDO questionDO = saveQuestion(questionDOs.get(i));
                questionDOs.set(i, questionDO);
            } catch (Exception e) {
                ExcelException excelException = new ExcelException(0, i + 1, -1, e);
                incorrectDataS.add(excelException);
                abnormalOccurrence = true;
            }
        }

        if (abnormalOccurrence) {
            transactionManager.rollback(status);
        } else {
            transactionManager.commit(status);
        }
        return incorrectDataS;
    }

    public List<QuestionDO> getTestquestion(Serializable id, HashMap<String,Boolean> parameterMap) {
        ArrayList<TestQuestion> testQuestionByTestId = testQuestionService.getTestQuestionByTestId(id.toString());
        List<String> questionIds = testQuestionByTestId.stream().map(testQuestion -> {
            return testQuestion.getQuestionId();
        }).collect(Collectors.toList());

        List<QuestionDO> questionDOS = getQuestionByIds(questionIds, parameterMap);
        return questionDOS;
    }

    public Boolean questionService(String id, String result) {
        UserQuestionDO userQuestionDO = userQuestionService.getUserQuestion("000000", id, false);

        if (userQuestionDO == null || userQuestionDO.getQuestionId() == null) {
            UserQuestionDO userNewQuestionDO = new UserQuestionDO();
            userNewQuestionDO.setQuestionId(id);
            userNewQuestionDO.setUserId("000000");
            userNewQuestionDO.setCollection(result);
            userNewQuestionDO.setProblemNumber(0);
            userNewQuestionDO.setErrorNumber(0);
            userQuestionService.saveUserQuestion(userNewQuestionDO);
            return true;
        }



        if (!result.equals(userQuestionDO.getCollection())){

            userQuestionDO.setCollection(result);

            userQuestionService.updateQuestionData(userQuestionDO);
        }
        return false;
    }
    public Boolean correctJudgment(String questionId, String answerId, String result) {
        double resultInt = 0;
        if (result.equals("1")) {
            resultInt = 100;
        }
        QuestionDO question = getQuestionById(questionId, null);
        if (question == null) {
            throw ReturnCodeExt.DAO_EXCEPTION.getException("question不存在");
        }

        AnswerDO answerDO = answerService.getAnswerById(answerId);
        if (answerDO == null) {
            throw ReturnCodeExt.DAO_EXCEPTION.getException("answerDO不存在");
        }


        AnswerResult answerResult = new AnswerResult(questionId, answerId, resultInt);
        UserQuestionDO userQuestionDO = userQuestionService.updateQuestionData(questionId, answerResult.getResult() == 100 ? 1 : 0);
        AnswerJournalDO answerJournalDO = new AnswerJournalDO();
        answerJournalDO.setQuestionId(questionId);
        answerJournalDO.setAnswerId(answerId);
        answerJournalDO.setReplyAnswer("");
        answerJournalDO.setUserQuestionId(userQuestionDO.getUserQuestionId());
        answerJournalDO.setReplyAnswerDetails("");
        answerJournalDO.setResultDetails(String.valueOf(resultInt));
        answerJournalService.saveAnswerJournal(answerJournalDO);

        return true;
    }
}

